Validate deep link args when resolving the start location#355
Merged
Conversation
NavController merges the deepLinkArgs intent extra over the validated deepLinkExtras (last write wins), so an external Intent could override the validated start location and load an arbitrary URL in the WebView. Empty each deepLinkArgs bundle before validating the start location. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
TurboSessionNavHostFragment.ensureDeeplinkStartLocationValid()validates the startlocationonly inside thedeepLinkExtrasintent extra (android-support-nav:controller:deepLinkExtras).AndroidX
NavControlleralso reads a second extra —deepLinkArgs(android-support-nav:controller:deepLinkArgs) — and merges it overdeepLinkExtraswhen assembling each destination's arguments (arguments.putAll(globalArgs)followed byarguments.putAll(deepLinkArgs[index]), so the later write wins). Because an exported Activity's launch intent is externally controllable, alocation(or any other argument) supplied viadeepLinkArgsoverrides the validated value and becomes the session's start destination — loading an unvalidated URL into the host's WebView.This ports hotwired/hotwire-native-android#200 to turbo-android.
Fix
ensureDeeplinkStartLocationValid()now sanitizes the launching intent'sdeepLinkArgsin addition to validatingdeepLinkExtras:deepLinkArgsper-destination bundle is emptied so it can't override the validated start location;deepLinkExtrasstartlocationwhose host doesn't match the configured start host is reverted to the configured start location, as before.Sanitization applies to every launching intent. Intent-origin signals are too weak to gate on —
callingPackageis only set forstartActivityForResultlaunches, andActivity.referreris backed by the attacker-settableEXTRA_REFERRER— so there is no reliable way to distinguish app-produced intents from external ones. Unconditional sanitization keeps legitimate same-host start locations working while preventing an external intent from steering the session to an arbitrary URL.Tests
TurboSessionNavHostFragmentTestcovers:deepLinkArgsare emptied so they can't override the validated start location.🤖 Generated with Claude Code